home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1988-12-16 | 31.4 KB | 1,175 lines | [ TEXT/MSWD]
(* © 1988, Apple Computer, Inc. All rights reserved. Window1.p: A HyperCard XCMD in MPW Pascal 2.0.2 by Joe Zuffoletto Version 1.0, 29 June 1988 Form: Window title,top,left,bottom,right Example: window "My Window",50,100,300,400 Notes: Window puts up a standard document window with scroll bars. The window can be dragged, resized, zoomed, and closed. Command-W is supported for closing the window. Command-spacebar toggles the menubar on and off, as in HyperCard. If you try to draw the window's title bar off the screen or under the menubar, Window will abort with an error message. Error messages can be examined by looking at HyperCard's global variable "the result" after calling Window. Window is MultiFinder friendly and works with HyperCard 1.2 or later. It supports multiple displays on the Mac II as well. You must supply your own code for displaying whatever you want to display in the window. ------------------------------------------------------------ To compile and link this file using MPW Pascal 2.0.2, select the following lines and press ENTER: Pascal Window1.p link -o "Hard Disk":HyperCard:"HyperCard Stacks":Home ∂ -rt XCMD=2000 -sn Main=Window ∂ Window1.p.o {MPW}Libraries:Interface.o ∂ {MPW}PLibraries:PasLib.o ∂ -m ENTRYPOINT Use other link files as necessary. The above link directives install the XCMD resource into the Home stack. You can substitute the name of any stack you want; be sure to provide the correct pathname. Also, make sure the target stack already has a resource fork or it won't work. You can create an empty resource fork in a stack with ResEdit. ------------------------------------------------------------ *) {$R-} {$S Window} UNIT DummyUnit; INTERFACE USES MemTypes,QuickDraw,OSIntf,ToolIntf,PasLibIntf,HyperXCmd; PROCEDURE EntryPoint(paramPtr:XCmdPtr); IMPLEMENTATION TYPE Str31 = String[31]; OffScrHandle = ^OffScrRecPtr; {Attach to refCon of a window} OffScrRecPtr = ^OffScrRecord; OffScrRecord = RECORD {Next month!} END; ScrollHandle = ^ScrollPtr; {Attach to refCon of a control} ScrollPtr = ^ScrollRecord; ScrollRecord = RECORD {Next month!} END; PROCEDURE Window(paramPtr:XCmdPtr);FORWARD; PROCEDURE EntryPoint(paramPtr:XCmdPtr); BEGIN Window(paramPtr); END; FUNCTION Min(int1,int2:INTEGER): INTEGER; BEGIN {Next month!} END; {Min} PROCEDURE InitBlit(theWindow:WindowPtr); BEGIN {Next month!} END; {InitBlit} PROCEDURE InvalContents(theWindow:WindowPtr; theOldSize:Rect); BEGIN {More to come next month!} EraseRect(theWindow^.portRect); InvalRect(theWindow^.portRect); END; {InvalContents} PROCEDURE DrawContents(theWindow:WindowPtr); BEGIN {Next month!} END; {DrawContents} PROCEDURE ScrollContents(theWindow:WindowPtr;dh,dv:INTEGER); BEGIN {Next month!} END; {ScrollContents} PROCEDURE MyScroll(theControl:ControlHandle;partCode:INTEGER); BEGIN {Next month!} END; {MyScroll} PROCEDURE Window(paramPtr:XCmdPtr); CONST minParamCount = 5; smallestHeight = 100; smallestWidth = 100; _WaitNextEvent = $A860; _Unimplemented = $A89F; active = 0; inactive = 255; MouseMovedEvt = $FA; SuspendResumeEvt = $01; SuspendEventMask = $1; ConvertScrapMask = $2; browseTool = 6069; HCWidth = 512; HCHeight = 342; padding = 16; VAR toolVis,patVis: BOOLEAN; msgVis,fatVis: BOOLEAN; hasWaitNextEvent: BOOLEAN; inBackGround,smallScreen: BOOLEAN; DoneFlag,HaveEvent: BOOLEAN; wTop,wLeft,wBottom,wRight: INTEGER; partCode,controlCode: INTEGER; largestHeight,largestWidth: INTEGER; dummy,charCode: INTEGER; screenWidth,screenHeight: INTEGER; myDocWidth,myDocHeight: INTEGER; eventPoint: Point; wRect,screenRect,dragRect: Rect; winSizeLimits: Rect; oldSize: Rect; newSize,dontCare: LONGINT; envError: OSErr; cursorRgn: RgnHandle; hScroll,vScroll: ControlHandle; whichControl: ControlHandle; myWindow,whichWindow: WindowPtr; fatBitsWindow: WindowPtr; HCrefresh: Str31; wT,wL,wB,wR,wTitle: Str255; toolStr,patStr,msgStr: Str255; widthStr,heightStr: Str255; myBits: BitMap; theEnv: SysEnvRec; myEvent: EventRecord; wRecord: WindowRecord; HCPort: GrafPtr; theOffScrHandle: OffScrHandle; theScrollHandle: ScrollHandle; myOffScr: OffScrRecord; myScrollRecord: ScrollRecord; FUNCTION TrapAvailable(tNumber: INTEGER; tType: TrapType):BOOLEAN; {Check to see if a given trap is implemented.} BEGIN TrapAvailable := NGetTrapAddress(tNumber, tType) <> GetTrapAddress(_Unimplemented); END; {TrapAvailable} FUNCTION CreateHScrollBar(theWindow:WindowPtr; theValue,theMin,theMax:INTEGER; theRefCon:LONGINT):ControlHandle; {Allocate and draw a horizontal scroll bar in theWindow. Return a controlHandle to the scroll bar.} VAR myWindowRect,hScrRect: Rect; BEGIN SetPort(theWindow); myWindowRect := theWindow^.portRect; SetRect(hScrRect,myWindowRect.left -1, myWindowRect.bottom - 15, myWindowRect.right - 14, myWindowRect.bottom + 1); CreateHScrollBar := NewControl(theWindow,hScrRect, 'MyHoriz',TRUE, theValue,theMin,theMax, scrollBarProc,theRefCon); END; {CreateHScrollBar} FUNCTION CreateVScrollBar(theWindow:WindowPtr; theValue,theMin,theMax:INTEGER; theRefCon:LONGINT):ControlHandle; {Allocate and draw a vertical scroll bar in theWindow. Return a controlHandle to the scroll bar.} VAR myWindowRect,vScrRect: Rect; BEGIN SetPort(theWindow); myWindowRect := theWindow^.portRect; SetRect(vScrRect,myWindowRect.right -15, myWindowRect.top - 1, myWindowRect.right + 1, myWindowRect.bottom - 14); CreateVScrollBar := NewControl(theWindow,vScrRect, 'MyVert',TRUE, theValue,theMin,theMax, scrollBarProc,theRefCon); END; {CreateVScrollBar} PROCEDURE InvalScroll(theWindow:WindowPtr); {Accumulate the rectangles occupied by theWindow's horizontal and vertical scroll bars into the update region.} VAR theRect,tallRect,wideRect: Rect; BEGIN SetPort(theWindow); theRect := theWindow^.portRect; ClipRect(theRect); {Accumulate tallRect, which is occupied by the vertical scroll bar } SetRect(tallRect,theRect.right-15, theRect.top, theRect.right, theRect.bottom); EraseRect(tallRect); InvalRect(tallRect); {Accumulate wideRect, which is occupied by the horizontal scroll bar } SetRect(wideRect,theRect.left, theRect.bottom-15, theRect.right, theRect.bottom); EraseRect(wideRect); InvalRect(wideRect); END; {InvalScroll} PROCEDURE Deactivate(theWindow:WindowPtr); {Deactivate the scroll bars in theWindow in accordance with the human interface guidelines. This means we must erase everything enclosed by the control rec- tangles.} VAR theControl: ControlHandle; theControlRect: Rect; BEGIN {I always title my scroll bars 'MyVert' and 'MyHoriz' so I can easily find them by walking a window's control list.} theControl := WindowPeek(theWindow)^.controlList; WHILE (theControl <> NIL) DO BEGIN IF (theControl^^.contrlTitle = 'MyVert') OR (theControl^^.contrlTitle = 'MyHoriz') THEN BEGIN theControlRect := theControl^^.contrlRect; InsetRect(theControlRect,1,1); EraseRect(theControlRect); END; {IF} theControl := theControl^^.nextControl; END; {WHILE} END; {Deactivate} PROCEDURE HiliteScrollBars(theWindow:WindowPtr); BEGIN {Reactivate the scroll bars; e.g., when we resume under MultiFinder. More next month!} HiliteControl(vScroll,INTEGER(active)); HiliteControl(hScroll,INTEGER(active)); END; {HiliteScrollBars} PROCEDURE MoveScrollBars(theWindow:WindowPtr); {Call this procedure after theWindow has changed size. MoveScrollBars erases theWindow's scroll bars, resizes them, and redraws them.} VAR myWindowRect: Rect; vScrRect,hScrRect: Rect; BEGIN myWindowRect := theWindow^.portRect; SetRect(hScrRect,myWindowRect.left - 1, myWindowRect.bottom - 15, myWindowRect.right - 14, myWindowRect.bottom + 1); SetRect(vScrRect,myWindowRect.right - 15, myWindowRect.top - 1, myWindowRect.right + 1, myWindowRect.bottom - 14); SetPort(theWindow); ClipRect(myWindowRect); {Hide and resize the scroll bars to fit the new window size.} HideControl(hScroll); HideControl(vScroll); MoveControl(hScroll,hScrRect.left,hScrRect.top); SizeControl(hScroll,(hScrRect.right - hScrRect.left), (hScrRect.bottom - hScrRect.top)); MoveControl(vScroll,vScrRect.left,vScrRect.top); SizeControl(vScroll,(vScrRect.right - vScrRect.left), (vScrRect.bottom - vScrRect.top)); HiliteScrollBars(theWindow); ShowControl(hScroll); ShowControl(vScroll); END; {MoveScrollBars} PROCEDURE ScrollWithThumb(theControl:ControlHandle; theEventPoint:Point); BEGIN {Next month!} END; {ScrollWithThumb} FUNCTION WhichDevice(thePoint:Point):GDHandle; {For machines that support color QuickDraw and multiple screens, WhichDevice figures out which screen thePoint is on and returns a GDHandle to that screen. thePoint might be where the mouse was clicked, for example. Thanks to Greg Marriott for this code.} VAR aDevice: GDHandle; foundOne: BOOLEAN; BEGIN aDevice := GetDeviceList; foundOne := FALSE; {Walk the device list until thePoint is contained in some device's screen rectangle.} WHILE (aDevice <> NIL) AND NOT foundOne DO BEGIN IF PtInRect(thePoint,aDevice^^.gdRect) THEN BEGIN WhichDevice := aDevice; foundOne := TRUE; END; aDevice := aDevice^^.gdNextGD; END; END; {WhichDevice} FUNCTION MenuBarHeight: INTEGER; {Returns the height of the menubar in pixels, as read from the low memory global mBarHeight.} CONST mBarHeight = $BAA; VAR menuBarHeightPtr: ^INTEGER; BEGIN menuBarHeightPtr := Pointer(mBarHeight); MenuBarHeight := menuBarHeightPtr^; END; {MenuBarHeight} FUNCTION OnAScreen(theRect:Rect):BOOLEAN; {OnAScreen returns FALSE if all of a window's title bar is off the screen or if any part of it is under the menubar. The portRect of the window to be checked should be passed in theRect.} CONST titleBarHeight = 18; VAR deskRgn: RgnHandle; topLeft,topRight: Point; BEGIN deskRgn := GetGrayRgn; topLeft.v := theRect.top - titleBarHeight; topLeft.h := theRect.left + titleBarHeight; topRight.v := topLeft.v; topRight.h := theRect.right - titleBarHeight; IF ((PtInRgn(topLeft,deskRgn)) OR (PtInRgn(topRight,deskRgn))) THEN OnAScreen := TRUE ELSE OnAScreen := FALSE; END; {OnAScreen} PROCEDURE ZoomIt(theWindow:WindowPtr;partCode:INTEGER; clickedWhere:Point); {ZoomIt supports more elegant window zooming on multiple screen systems. theWindow will zoom to fill whatever screen the zoom box was on when it was clicked. The window state toggles between original size and zoomed size, as usual. Thanks to Greg Marriott for this code.} CONST titleBarHeight = 18; TYPE WStatePtr = ^WStateData; WStateHandle = ^WStatePtr; VAR oldRect,newRect: Rect; maxHeight: INTEGER; BEGIN oldRect := theWindow^.portRect; IF theEnv.hasColorQD THEN BEGIN newRect := WhichDevice(clickedWhere)^^.gdRect; IF WhichDevice(clickedWhere) = GetMainDevice THEN newRect.top := newRect.top + MenuBarHeight; END newRect := GetGrayRgn^^.rgnBBox; newRect.left := newRect.left + 2; newRect.top := newRect.top + titleBarHeight + 2; newRect.right := newRect.right - 3; newRect.bottom := newRect.bottom - 3; IF NOT EqualRect(oldRect,newRect) THEN WITH WindowPeek(theWindow)^ DO WStateHandle(dataHandle)^^.stdState := newRect; SetPort(theWindow); EraseRect(whichWindow^.portRect); InvalRect(whichWindow^.portRect); ZoomWindow(theWindow,partcode,FALSE); END; {ZoomIt} {$I XCmdGlue.inc} PROCEDURE Fail(errStr:Str255); {Fail returns errStr to HyperCard and exits the XCMD. errStr can then be checked by inspecting HyperCard's global variable "the result." See "XCMD's for Hyper- Card" by Gary Bond (MIS Press, 1988) for more details. © 1988 by Gary Bond All rights reserved. You may use this code for NON-COMMERCIAL purposes.} BEGIN paramPtr^.returnValue := PasToZero(errStr); SysBeep(1); EXIT(Window); END; {Fail} PROCEDURE CheckParamCount; {CheckParamCount sees if the number of parameters passed to the XCMD matches the number expected. If not, we exit from the XCMD with an error message. See "XCMD's for HyperCard" by Gary Bond (MIS Press, 1988) for more details. © 1988 by Gary Bond All rights reserved. You may use this code for NON-COMMERCIAL purposes.} VAR numParams: INTEGER; BEGIN numParams := paramPtr^.paramCount; IF(numParams <> minParamCount) THEN Fail('Form: HyperWindow "Window Title",top,left,bottom,right'); END; {CheckParamCount} FUNCTION GetHCVersion: Str255; {Return a string containing the version of HyperCard being used; e.g., '1.2'} BEGIN ZeroToPas(EvalExpr('the version')^,GetHCVersion); END; {GetHCVersion} PROCEDURE HideWindoids; {Get and save the visible state of the tool, pattern, message and fatbits windoids; then hide them if they are showing.} VAR toolH,patH,msgH,fatH: Handle; PROCEDURE HideFatBits; {HyperCard does not have a built-in command for hiding and showing the fatbits windoid, so we have to do it ourselves. HideFatBits walks the window list until it finds a window with title "FatBits," then hides it if the visible field of its WindowRecord is true. HideFatBits also saves the WindowPtr to the fatbits windoid so we can use it later (e.g., to show the windoid again).} CONST windowList = $9D6; {Low memory global location.} VAR theWindow: WindowPeek; theWindowPtr: ^WindowPtr; BEGIN theWindowPtr := Pointer(windowList); theWindow := WindowPeek(theWindowPtr^); fatVis := FALSE; WHILE (theWindow <> NIL) DO BEGIN IF (theWindow^.titleHandle^^ = 'FatBits') THEN BEGIN fatBitsWindow := WindowPtr(theWindow); IF (theWindow^.visible = TRUE) THEN BEGIN fatVis := TRUE; HideWindow(fatBitsWindow); theWindow := NIL; END; END; IF (theWindow <> NIL) THEN theWindow := WindowPeek(theWindow)^.nextWindow; END; {WHILE} END; {HideFatBits} BEGIN {HideWindoids} {Get visible state of windoids.} toolH := EvalExpr('visible of tool window'); ZeroToPas(toolH^,toolStr); DisposHandle(toolH); toolVis := StrToBool(toolStr); patH := EvalExpr('visible of pattern window'); ZeroToPas(patH^,patStr); DisposHandle(patH); patVis := StrToBool(patStr); msgH := EvalExpr('visible of message window'); ZeroToPas(msgH^,msgStr); DisposHandle(msgH); msgVis := StrToBool(msgStr); {Hide the ones that are showing.} HideFatBits; IF toolVis THEN SendHCMessage('hide tool window'); IF patVis THEN SendHCMessage('hide pattern window'); IF msgVis THEN SendHCMessage('hide message window'); END; {HideWindoids} PROCEDURE ShowWindoids; {This routine assumes HideWindoids has been called before. ShowWindoids restores the visible state of the windoids to that saved by HideWindoids.} BEGIN IF toolVis THEN SendHCMessage('show tool window'); IF patVis THEN SendHCMessage('show pattern window'); IF msgVis THEN SendHCMessage('show message window'); {As in HideWindoids, we must take care of the FatBits windoid ourselves.} IF fatVis THEN BEGIN ShowWindow(fatBitsWindow); SelectWindow(fatBitsWindow); END; END; {ShowWindoids} PROCEDURE ToggleMenuBar; {Set the visible of the menubar to not the visible of the menubar.} BEGIN IF MenuBarHeight = 0 THEN SendHCMessage('show menubar') ELSE SendHCMessage('hide menubar'); END; {ToggleMenuBar} PROCEDURE GetHCBitMap; BEGIN {Next month!} END; {GetHCBitMap} PROCEDURE AdjustCursor; {AdjustCursor changes cursorRgn to the region that contains the cursor. As soon as the cursor moves out of cursorRgn, we get an event and can change the cursor and cursorRgn again. cursorRgn is either the content region of our window or the region containing everything BUT the content region of our window.} VAR mousePt: Point; myWinContRect: Rect; myWinContRgn: RgnHandle; deskRgn: RgnHandle; handHdl: CursHandle; BEGIN SetPort(myWindow); GetMouse(mousePt); LocalToGlobal(mousePt); myWinContRgn := NewRgn; {Calculate the "work region" of our window, which is its content region minus the scroll bars and grow icon. This is the region within which we want the cursor to change to HyperCard's browse tool, and outside of which we want it to be an arrow.} WITH WindowPeek(myWindow)^.contRgn^^.rgnBBox DO SetRect(myWinContRect,left, top, right - 15, bottom - 15); RectRgn(myWinContRgn,myWinContRect); IF PtInRect(mousePt,myWinContRect) THEN BEGIN {The cursor is in the work region of our window. Set to browse tool.} handHdl := GetCursor(browseTool); IF (handHdl <> NIL) THEN SetCursor(handHdl^^) ELSE {Set to arrow if can't find browse tool resource.} InitCursor; {Set the cursor region equal to our window's work region.} SetEmptyRgn(cursorRgn); CopyRgn(myWinContRgn,cursorRgn); END ELSE BEGIN {The cursor is outside our window. Set to arrow.} InitCursor; {Get the current desktop region.} deskRgn := GetGrayRgn; {Set cursorRgn to the desktop region's bounding box. It is important to add the menu bar area to cursorRgn too.} SetRectRgn(cursorRgn, deskRgn^^.rgnBBox.left, deskRgn^^.rgnBBox.top, deskRgn^^.rgnBBox.right, deskRgn^^.rgnBBox.bottom); {Punch out our window's content region from the big region.} DiffRgn(cursorRgn,myWinContRgn,cursorRgn); END; DisposeRgn(myWinContRgn); END; {AdjustCursor} BEGIN {Main Program} {Check the HyperCard version. Must be 1.2 or greater.} IF GetHCVersion < '1.2' THEN Fail('Sorry, must have HyperCard 1.2 or greater.'); {Save thy grafPort upon entering!} GetPort(HCPort); {Check and reset our environment.} CheckParamCount; FlushEvents(everyEvent,0); InitCursor; {Find out what kind of machine we're running on.} envError := SysEnvirons(1,theEnv); IF (envError <> noErr) THEN Fail('SysEnvirons call failed.'); {Convert HyperTalk input parameters for use here.} ZeroToPas(paramPtr^.params[1]^,wTitle); ZeroToPas(paramPtr^.params[2]^,wT); ZeroToPas(paramPtr^.params[3]^,wL); ZeroToPas(paramPtr^.params[4]^,wB); ZeroToPas(paramPtr^.params[5]^,wR); wTop := INTEGER(StrToNum(wT)); wLeft := INTEGER(StrToNum(wL)); wBottom := INTEGER(StrToNum(wB)); wRight := INTEGER(StrToNum(wR)); {If window size parameters are too small or illegal, set the window to a predefined minimum size.} IF ((wRight - wLeft) < smallestWidth) THEN wRight := wLeft + smallestWidth; IF ((wBottom - wTop) < smallestHeight) THEN wBottom := wTop + smallestHeight; {Make sure the user is not trying to draw the window off the screen or under the menubar.} SetRect(wRect,wLeft,wTop,wRight,wBottom); IF NOT OnAScreen(wRect) THEN Fail('You are trying to draw your window off the screen!'); {Get the bounds of the desktop.} screenRect := GetGrayRgn^^.rgnBBox; {If we have a small screen, make a note of it so we can hide the card window during context switches under MultiFinder.} ZeroToPas(EvalExpr('item 3 of the screenRect')^,widthStr); screenWidth := INTEGER(StrToNum(widthStr)); ZeroToPas(EvalExpr('item 4 of the screenRect')^, heightStr); screenHeight := INTEGER(StrToNum(heightStr)); IF (screenWidth = 512) AND (screenHeight = 342) THEN smallScreen := TRUE ELSE smallScreen := FALSE; HideWindoids; IF MenuBarHeight > 0 THEN menuWasHidden := FALSE ELSE menuWasHidden := TRUE; {This is for scrolling and will be explained next month.} theOffScrHandle := OffScrHandle(NewHandle (SizeOf(OffScrRecord))); IF MemError <> noErr THEN Fail('Out of memory. Buy more.'); myDocWidth := HCWidth + padding; myDocHeight := HCHeight + padding; WITH theOffScrHandle^^ DO BEGIN {Next month!} END; GetHCBitMap; {Draw the window!} myWindow := NewWindow(@wRecord,wRect, wTitle,TRUE,zoomDocProc, WindowPtr(-1),TRUE,1); IF (myWindow = NIL) THEN BEGIN ShowWindoids; Fail('Not enough memory to draw window.'); END ELSE BEGIN {This is for scrolling. Stay tuned....} SetWRefCon(myWindow,LONGINT(theOffScrHandle)); InitBlit(myWindow); DrawGrowIcon(myWindow); theScrollHandle := ScrollHandle(NewHandle (SizeOf(ScrollRecord))); IF MemError <> noErr THEN Fail('Out of memory. Buy more.'); {Draw horizontal and vertical scroll bars in our window.} hScroll := CreateHScrollBar(myWindow,0,0, myDocWidth, LONGINT(theScrollHandle)); vScroll := CreateVScrollBar(myWindow,0,0, myDocHeight, LONGINT(theScrollHandle)); HiliteScrollBars(myWindow); DrawContents(myWindow); SetRect(dragRect,screenRect.left + 4, screenRect.top, screenRect.right - 4, screenRect.bottom - 4); largestHeight := screenRect.bottom - screenRect.top; largestWidth := screenRect.right - screenRect.left; SetRect(winSizeLimits,smallestWidth, smallestHeight, largestWidth, largestHeight); HCRefresh := 'Go to this card'; cursorRgn := NewRgn; inBackGround := FALSE; DoneFlag := FALSE; REPEAT {Call WaitNextEvent, if available. Otherwise call GetNextEvent.} IF hasWaitNextEvent THEN HaveEvent := WaitNextEvent(everyEvent, myEvent,30,cursorRgn) ELSE BEGIN HaveEvent := GetNextEvent(everyEvent,myEvent); AdjustCursor; END; IF HaveEvent THEN BEGIN IF (myEvent.what = app4Evt) THEN {Pre-process app4Evt's fed to us by MultiFinder.} CASE BSR(myEvent.message,24) OF MouseMovedEvt: AdjustCursor; SuspendResumeEvt: BEGIN myEvent.what := activateEvt; {Resume event.} IF (BAND(myEvent.message,SuspendEventMask) <> 0) THEN inBackground := FALSE ELSE {Suspend event.} inBackground := TRUE; myEvent.message := LONGINT(myWindow); END; {SuspendResumeEvt} END; {CASE BSR} END; {IF HaveEvent} CASE myEvent.what OF mouseDown: BEGIN partCode := FindWindow(myEvent.where,whichWindow); IF (whichWindow = myWindow) THEN BEGIN {Deal with mouse hits to our window.} CASE partCode OF inDrag: BEGIN SelectWindow(whichWindow); {DragWindow bug} DragWindow(whichWindow,myEvent.where, dragRect); SendCardMessage(HCrefresh); AdjustCursor; END; inGrow: IF StillDown THEN {GrowWindow bug} BEGIN oldSize := whichWindow^.portRect; newSize := GrowWindow(whichWindow, myEvent.where, winSizeLimits); IF (newSize <> 0) THEN BEGIN InvalScroll(whichWindow); SizeWindow(whichWindow, LOWORD(newSize), HIWORD(newSize),FALSE); InvalContents(whichWindow,oldSize); DrawGrowIcon(whichWindow); MoveScrollBars(whichWindow); END; {IF newSize} END; {IF StillDown} END; {inGrow} inZoomIn,inZoomOut: BEGIN IF (TrackBox(whichWindow, myEvent.where, partCode)) THEN BEGIN InvalScroll(whichWindow); ZoomIt(whichWindow,partCode, myEvent.where); InvalContents(whichWindow,oldSize); DrawGrowIcon(whichWindow); MoveScrollBars(whichWindow); END; {IF TrackBox} END; {inZoomIn,inZoomOut} inContent: BEGIN SetPort(whichWindow); eventPoint := myEvent.where; GlobalToLocal(eventPoint); controlCode := FindControl(eventPoint, whichWindow, whichControl); ClipRect(whichWindow^.portRect); IF (controlCode = inThumb) THEN ScrollWithThumb(whichControl,eventPoint) ELSE IF (controlCode <> 0) THEN dummy := TrackControl(whichControl, eventPoint, @MyScroll); END; {inContent} inGoAway: BEGIN IF (TrackGoAway(whichWindow,myEvent.where)) THEN DoneFlag := TRUE; END; {inGoAway} END; {CASE partCode} END; {IF whichWindow = myWindow} END; {mouseDown} activateEvt: BEGIN IF (WindowPtr(myEvent.message) = myWindow) THEN BEGIN SetPort(myWindow); ClipRect(myWindow^.portRect); DrawGrowIcon(myWindow); IF inBackground THEN BEGIN {We've been sent behind another application under MultiFinder, so deactivate the scroll bars and show the menubar if it was hidden.} Deactivate(myWindow); IF smallScreen THEN ShowHide(WindowPtr(HCPort),FALSE); IF MenuBarHeight = 0 THEN BEGIN SendHCMessage('show menubar'); menuWasHidden := TRUE; END ELSE menuWasHidden := FALSE; END ELSE BEGIN {We've been brought to the front under Multi- Finder, so reactivate the scroll bars and hide the menubar if it was hidden before.} ShowHide(WindowPtr(HCPort),TRUE); IF menuWasHidden THEN SendHCMessage('hide menubar'); DrawControls(myWindow); HiliteScrollBars(myWindow); FlushEvents(everyEvent,0); END; {IF inBackground} END; {IF WindowPtr} END; {activateEvt} updateEvt: BEGIN {Handle updates to our window.} IF (WindowPtr(myEvent.message) = myWindow) THEN BEGIN {Always do this stuff} SetPort(myWindow); BeginUpdate(myWindow); ClipRect(myWindow^.portRect); DrawGrowIcon(myWindow); {Always do this stuff under single Finder but only if in foreground under MultiFinder} IF NOT inBackground THEN BEGIN HiliteScrollBars(myWindow); DrawControls(myWindow); AdjustCursor; END; {Always do this stuff} DrawContents(myWindow); EndUpdate(myWindow); END {IF myEvent.message} {Handle updates to HyperCard's card window.} ELSE IF (WindowPtr(myEvent.message) = WindowPtr(HCPort)) THEN BEGIN SendHCMessage(HCRefresh); {Must zero out card window's update region ourselves because the SendHCMessage call doesn't do it, and we'll wind up in an infinite loop if we don't.} BeginUpdate(WindowPtr(HCPort)); EndUpdate(WindowPtr(HCPort)); END; {IF... ELSE} END; {updateEvt} keyDown: BEGIN IF (BitAnd(myEvent.modifiers,cmdKey) <> 0) THEN BEGIN charCode := BitAnd(myEvent.message, charCodeMask); {Pressing command-spacebar toggles the menubar.} IF (CHR(charCode) = ' ') THEN ToggleMenuBar; {Pressing command-W closes the window and exits the XCMD.} IF (CHR(charCode) = 'w') THEN DoneFlag := True; END; END; END; {CASE myEvent.what} UNTIL (DoneFlag = True); {Clean up and get outta here!} DisposeRgn(cursorRgn); DisposHandle(Handle(theOffScrHandle)); DisposHandle(Handle(theScrollHandle)); CloseWindow(myWindow); SendCardMessage(HCrefresh); ShowWindoids; InitCursor; FlushEvents(everyEvent,0); {Restore thy grafPort} SetPort(HCPort); END; {IF myWindow...ELSE} END; {Main} END. {Window}